﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Text;

using iTextSharp.text.pdf;
using iTextSharp.text;
using ACRODISTXLib;
using System.Diagnostics;

namespace AKMII.DMRA.Common
{
    public sealed class Utility
    {
        public static string BuildPassword(int passwordlength)
        {
            StringBuilder password = new StringBuilder();

            do
            {
                password.Append(Guid.NewGuid().ToString().Replace("-", string.Empty));
            }
            while (password.Length < passwordlength);

            return password.ToString(0, passwordlength);
        }

        public static string GetNumber(int i)
        {
            string number = string.Empty;

            if (i > 0)
            {
                if (i < 10)
                {
                    number = "0" + i.ToString();
                }
                else
                {
                    number = i.ToString();
                }
            }

            return number;
        }    

        public static MonthSetting GetCurrentMonthSetting(List<MonthSetting> settings, DateTime date)
        {
            foreach (MonthSetting setting in settings)
            {
                if (date <= setting.EndDate && date >= setting.StartDate)
                {
                    return setting;
                }
            }

            return null;
        }

        public static void Upload(string srcPath, 
            string dstUrl, string userName, string password)
        {
            FileStream stream = null;
            Stream requestStream = null;
            FtpWebResponse response = null;
            try
            {
                const int size = 2048;
                byte[] buffer = new byte[size];

                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(dstUrl);
                request.Method = WebRequestMethods.Ftp.UploadFile;
                request.Credentials = new NetworkCredential(userName, password);
                request.Proxy = null;
                requestStream = request.GetRequestStream();

                int count = 0;
                stream = File.OpenRead(srcPath);
                for (int n = stream.Read(buffer, 0, size); n > 0; n = stream.Read(buffer, 0, size))
                {
                    requestStream.Write(buffer, 0, n);
                    count += n;
                }
                stream.Close();
                requestStream.Close();
                stream = null;
                requestStream = null;
                Logger.Info(string.Format("{0} bytes were uploaded to {1}.", count, dstUrl));

                response = (FtpWebResponse)request.GetResponse();
                Logger.Info(string.Format("Upload File Complete, status {0}", response.StatusDescription));
                response.Close();
                response = null;
            }
            catch (Exception e)
            {
                Logger.Error("Exception occurs in upload file to DMRA", e);

                if (stream != null)
                {
                    stream.Close();
                    stream = null;
                }
                if (requestStream != null)
                {
                    requestStream.Close();
                    requestStream = null;
                }
                if (response != null)
                {
                    response.Close();
                    response = null;
                }
            }
        }

        public static string GetIndex(int index)
        {
            string title = string.Empty;

            if (index < 1000)
            {
                title = index.ToString();

                switch (title.Length)
                {
                    case 1:
                        title = title.Insert(0, "000");
                        break;
                    case 2:
                        title = title.Insert(0, "00");
                        break;
                    case 3:
                        title = title.Insert(0, "0");
                        break;
                    default:
                        break;
                }
            
            }
            else
            {
                title = index.ToString();
            }

            return title;
        }

        public static string GetMonthName(int month)
        {
            switch (month)
            {
                case 1:
                    return "January";
                case 2:
                    return "February";
                case 3:
                    return "March";
                case 4:
                    return "April";
                case 5:
                    return "May";
                case 6:
                    return "June";
                case 7:
                    return "July";
                case 8:
                    return "August";
                case 9:
                    return "September";
                case 10:
                    return "October";
                case 11:
                    return "November";
                case 12:
                    return "December";
                default:
                    return "UNKOWN";
            }
        }

        public static DateTime GetDayInMonth(int year, int month, DayOfWeek dayOfWeek, int seq)
        {
            DateTime dateTime = DateTime.Now;
            DateTime nextMonthDate = new DateTime(year, month, 1).AddMonths(1);

            for (int day = 1; day <= DateTime.DaysInMonth(nextMonthDate.Year, nextMonthDate.Month); day++)
            {
                dateTime = new DateTime(nextMonthDate.Year, nextMonthDate.Month, day);

                if (dateTime.DayOfWeek == dayOfWeek)
                {
                    break;
                }
            }

            dateTime = dateTime.AddDays((seq - 1) * 7);

            return dateTime;

            /*
            int count = 0;
            DateTime dateTime = DateTime.Now;
            DateTime nextMonthDate = new DateTime(year, month, 1).AddMonths(1);
            int daysCount = DateTime.DaysInMonth(nextMonthDate.Year, nextMonthDate.Month);
            for (int day = 1; day <= daysCount; day++)
            {
                DateTime dt = new DateTime(nextMonthDate.Year, nextMonthDate.Month, day);

                if (dt.DayOfWeek == dayOfWeek)
                {
                    count++;

                    if (count == seq)
                    {
                        dateTime = dt;
                        break;
                    }
                }
            }

            if (count != seq)
            {
                nextMonthDate = new DateTime(year, month, 1).AddMonths(2);
                daysCount = DateTime.DaysInMonth(nextMonthDate.Year, nextMonthDate.Month);

                for (int day = 1; day <= daysCount; day++)
                {
                    DateTime dt = new DateTime(nextMonthDate.Year, nextMonthDate.Month, day);

                    if (dt.DayOfWeek == dayOfWeek)
                    {
                        count++;

                        if (count == seq)
                        {
                            dateTime = dt;
                            break;
                        }
                    }
                }
            }

            return dateTime;*/
        }

        public static void ExtractPages(string inputFile, string outputFile)
        {
            // get input document
            PdfReader inputPdf = new PdfReader(inputFile);

            // retrieve the total number of pages
            int pageCount = inputPdf.NumberOfPages;

            // load the input document
            Document inputDoc =
                new Document(inputPdf.GetPageSizeWithRotation(1));

            // create the filestream
            using (FileStream fs = new FileStream(outputFile, FileMode.Create))
            {
                // create the output writer
                PdfWriter outputWriter = PdfWriter.GetInstance(inputDoc, fs);
                inputDoc.Open();

                PdfContentByte cb1 = outputWriter.DirectContent;

                // copy pages from input to output document
                for (int i = 1; i <= pageCount; i++)
                {
                    inputDoc.SetPageSize(inputPdf.GetPageSizeWithRotation(1));
                    inputDoc.NewPage();

                    PdfImportedPage page =
                        outputWriter.GetImportedPage(inputPdf, i);
                    int rotation = inputPdf.GetPageRotation(i);


                    if (rotation == 90 || rotation == 270)
                    {
                        cb1.AddTemplate(page, 0, -1f, 1f, 0, 0,
                            inputPdf.GetPageSizeWithRotation(i).Height);

                    }
                    else
                    {
                        cb1.AddTemplate(page, -1f, 0, 0, -1f,
                            inputPdf.GetPageSizeWithRotation(i).Width,
                            inputPdf.GetPageSizeWithRotation(i).Height);
                    }

                }
                inputDoc.Close();
            }
        }

        public static void RotatePdf(string input, string output)
        {
            PdfReader inputPdf = new PdfReader(input);
            int pageCount = inputPdf.NumberOfPages;
            Document inputDoc = new Document(inputPdf.GetPageSizeWithRotation(1));

            using (FileStream fs = new FileStream(output, FileMode.Create))
            {
                PdfWriter outputWriter = PdfWriter.GetInstance(inputDoc, fs);
                inputDoc.Open();
                PdfContentByte cb1 = outputWriter.DirectContent; 

                for (int i = 1; i <= pageCount; i++)
                {
                    inputDoc.SetPageSize(inputPdf.GetPageSizeWithRotation(1).Rotate());
                    inputDoc.NewPage();

                    PdfImportedPage page =
                     outputWriter.GetImportedPage(inputPdf, i);
                    int rotation = inputPdf.GetPageRotation(i);

                    if (rotation == 90 || rotation == 270)
                    {
                        cb1.AddTemplate(page, 1f, 0, 0, 1f,
                            0, 0);
                    }
                    else
                    {
                        cb1.AddTemplate(page, 0, 1f, -1f, 0,
                            inputPdf.GetPageSizeWithRotation(i).Height, 0);
                    }
                }

                inputDoc.Close();
            }

        }

        public static void ConvertToPdf(string input, string output)
        {
            try
            {
                PdfDistiller pdfDistiller = new PdfDistiller();
                pdfDistiller.FileToPDF(input, output.Replace(".pdf", "_temp.pdf"), string.Empty);
                File.Delete(input);
                File.Delete(input.Replace(".ps", "_temp.log"));

                RotatePdf(output.Replace(".pdf", "_temp.pdf"), output);
                File.Delete(output.Replace(".pdf", "_temp.pdf"));
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                ExitAdobeProcess();
            }
        }

        public static void ConvertToPdfWithoutRotate(string input, string output)
        {
            try
            {
                PdfDistiller pdfDistiller = new PdfDistiller();
                pdfDistiller.FileToPDF(input, output, string.Empty);
                File.Delete(input);
                File.Delete(input.Replace(".ps", ".log"));
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                ExitAdobeProcess();
            }
        }

        private static void ExitAdobeProcess()
        {
            Process[] processes = Process.GetProcessesByName("acrodist");
            if (processes != null && processes.Length > 0)
            {
                foreach (var p in processes)
                {
                    p.Kill();
                }
            }
        }
    }
}
